#include "gif.h"
#include <multimedia/image/image_pixel_map.h>
#include <HiLog/log.h>
#ifdef __cplusplus
extern "C"{
#endif
/** Allocation failed. */
int ANDROID_BITMAP_RESULT_ALLOCATION_FAILED = -3;

static constexpr int32_t PIXEL_OFFSET = 588 * 342 + 360;

int lockPixels(JNIEnv *env, jobject jbitmap, GifInfo *info, void **pixels) {
	OhosPixelMapInfo bitmapInfo;
	if (GetImageInfo(env, jbitmap, bitmapInfo) == OHOS_IMAGE_RESULT_SUCCESS) {
		info->stride = bitmapInfo.width;
	} else {
		throwException(env, RUNTIME_EXCEPTION_BARE, "Could not get bitmap info ");
		return -2;
	}

	HiLogPrint((LogType)0,(LogLevel)4,0, "GetImageInfo",  "output:width[%{public}u], height[%{public}u], format[%{public}d]", bitmapInfo.width, bitmapInfo.height, bitmapInfo.pixelFormat);

	const int lockPixelsResult = AccessPixels(env, jbitmap, pixels);
	if (lockPixelsResult == OHOS_IMAGE_RESULT_SUCCESS) {
		return 0;
	}

	char *message;
	switch (lockPixelsResult) {
		case OHOS_IMAGE_RESULT_BAD_PARAMETER:
			message = "Lock pixels error, bad parameter";
			break;
		case OHOS_IMAGE_RESULT_JNI_EXCEPTION:
			message = "Lock pixels error, JNI exception";
			break;
		default:
			message = "Lock pixels error";
	}
	throwException(env, RUNTIME_EXCEPTION_BARE, message);
	return -2;
}

void unlockPixels(JNIEnv *env, jobject jbitmap) {
	const int unlockPixelsResult = UnAccessPixels(env, jbitmap);
	if (unlockPixelsResult == OHOS_IMAGE_RESULT_SUCCESS) {
		return;
	}
	char *message;
	switch (unlockPixelsResult) {
		case OHOS_IMAGE_RESULT_BAD_PARAMETER:
			message = "Unlock pixels error, bad parameter";
			break;
		case OHOS_IMAGE_RESULT_JNI_EXCEPTION:
			message = "Unlock pixels error, JNI exception";
			break;
		default:
			message = "Unlock pixels error";
	}
	throwException(env, RUNTIME_EXCEPTION_BARE, message);
}

JNIEXPORT jlong JNICALL
Java_pl_droidsonroids_gif_GifInfoHandle_renderFrame(JNIEnv *env, jclass handleClass, jlong gifInfo, jobject jbitmap) {
	GifInfo *info = (GifInfo *) (intptr_t) gifInfo;
	if (info == NULL)
		return -1;

	long renderStartTime = getRealTime();
	void *pixels;
	if (lockPixels(env, jbitmap, info, &pixels) != 0) {
		return 0;
	}
	DDGifSlurp(info, true, false);
	if (info->currentIndex == 0) {
		prepareCanvas((argb*)pixels, info);
	}
	const uint_fast32_t frameDuration = getBitmap((argb*)pixels, info);
	unlockPixels(env, jbitmap);
	return calculateInvalidationDelay(info, renderStartTime, frameDuration);
}

#ifdef __cplusplus
}
#endif